package com.yunxi.log;

import com.alibaba.fastjson.JSON;
import io.swagger.annotations.ApiOperation;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Method;
import java.nio.charset.Charset;
import java.util.Map;

/**
 * Created by xuruzi on 2019/3/7.
 * <p>
 * spring aop 切面
 * <p>
 * 处理web请求,进入controller前记录log日志
 */
@Component
@Aspect
public class LogBeforeAspect {

    private static final Logger logger = LoggerFactory.getLogger(LogBeforeAspect.class);


    /**
     * 定义切面
     * 指定的controller里的所有方法
     * 可以使用表达式批量指定
     */
    @Pointcut("execution(* com.yunxi.controller..*.*(..))")
    public void pointCut() {
    }


    @Before("pointCut()")
    public void addBeforeLog(JoinPoint joinPoint) {

        RequestAttributes ra = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes sra = (ServletRequestAttributes) ra;
        HttpServletRequest request = sra.getRequest();
        String uri = request.getRequestURI();//请求路径
        String methodDescription = "";
//        String params = JSON.toJSONString(request.getParameterMap());
        String params = request.getQueryString();
        if(params == null || "".equals(params)){
            try {
                params = HttpRequestWrapperUtil.getBodyString(request);
            }catch (IOException e2){

            }
        }

        String targetName = joinPoint.getTarget().getClass().getName();
        String methodName = joinPoint.getSignature().getName();
        Object[] arguments = joinPoint.getArgs();
        try {
            Class targetClass = Class.forName(targetName);
            Method[] methods = targetClass.getMethods();

            for (Method m : methods) {
                if (m.getName().equals(methodName)) {
                    Class[] clazzs = m.getParameterTypes();
                    if (clazzs.length == arguments.length) {
                        if (m.getDeclaredAnnotation(LogBefore.class) != null) {
                            methodDescription = m.getDeclaredAnnotation(LogBefore.class).description();
                            break;
                        } else if (m.getDeclaredAnnotation(ApiOperation.class) != null) {
                            methodDescription = m.getDeclaredAnnotation(ApiOperation.class).value();
                            break;
                        }
                    }
                }
            }

            logger.info("uri:{} , description:{} \n" +
                            ", class:{} , method:{} , params:{}"
                    , uri
                    , methodDescription
                    , targetName
                    , methodName
                    , params
            );
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("uri:{} , description:{}" +
                            ", class:{} , method:{} , params:{}" +
                            " errMsg:{}"
                    , uri
                    , methodDescription
                    , targetName
                    , methodName
                    , params
                    , e
            );
        }
    }

}
